<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        body{
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .container{
            padding: 20px;
            position: relative;
            background-color: #ccc;
        }
        .imageDiv{
            display: flex;
            gap: 20px;
        }

        .handelImageDiv{
            height: 450px;
            width: 450px;
        }
        .resultImageDiv{
            height: 450px;
            width: 160px;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            gap: 20px;
        }
        .resultImageDiv div{
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .resultImageDiv :where(img,canvas){
            height: 195px;
            width: 195px;
            border: 1px dashed #4A98F7;
        }
        .resultImageDiv img::before {
            background-color: #eeeeee;
            border: #aaaaaa;
            display: block;
            height: 100%;
            content: attr(alt);
            text-align: center;
        }

        .resultImageDiv span{
            margin-top: 10px;
            font-weight: 450;
            font-size: 18px;
            color: cornflowerblue;
        }

        .clipImgDiv{
            position: absolute;
            height: 450px;
            width: 450px;
            top: 20px;
            left: 20px;
            background-color: #11111150;
        }
        .moveClipDiv{
            height: 150px;
            width: 150px;
            position: absolute;
            top: calc(50% - 75px);
            left: calc(50% - 75px);
            background-color: #ffffff60;
            border: 1px solid #ccc;
            min-width: 100px;
            min-height: 100px;
        }
        .selectMoveDiv{
            position: absolute;
            cursor: move;
            height: 80%;
            width: 80%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }

        .option{
            position: absolute;
            height: 20px;
            width: 20px;
            background-color: #fff;
        }



        .dragLeftTop{
            top:  0;
            left:  0 ;
            cursor: nw-resize;
            clip-path: polygon(0% 0%,100% 0%,100% 20%,20% 20%,20% 100%,0% 100%);
            transform: translate(-10%,-10%);
        }
        .dragLeftCenter{
            top:  50%;
            left: 0% ;
            cursor: w-resize;
            clip-path: inset(0% 80% 0% 0%);
            transform: translate(-10%,-50%);

        }
        .dragLeftBottom{
            top: 100%;
            left: 0%;
            cursor: sw-resize;
            clip-path: polygon(0% 0%,20% 0%,20% 80%,100% 80%,100% 100%,0% 100%);
            transform: translate(-10%,-85%);
        }
        .dragTopCenter{
            top: 0% ;
            left: 50%;
            cursor: n-resize;
            clip-path: inset(0% 0% 80% 0%);
            transform: translate(-50%,-10%);
        }
        .dragBottomCenter{
            top: 100%;
            left: 50% ;
            cursor: s-resize;
            clip-path: inset( 0% 0% 80% 0%);
            transform: translate(-50%,-5%);
        }
        .dragRightTop{
            top: 0% ;
            left: 100%;
            cursor: ne-resize;
            clip-path: polygon(0% 0%,100% 0%,100% 100%,80% 100%,80% 20%,0% 20%);
            transform: translate(-90%,-10%);
        }
        .dragRightCenter{
            top: 50% ;
            left:100% ;
            cursor: e-resize;
            clip-path: inset( 0% 80% 0% 0%);
            transform: translate(-10%,-50%);
        }
        .dragRightBottom{
            top: 100%;
            left: 100%;
            cursor: se-resize;
            clip-path: polygon(80% 0%,100% 0%,100% 100%,0% 100%,0% 80%,80% 80%);
            transform: translate(-90%,-85%);
        }

        .handelButton{
            margin-top: 20px;
        }

        .handelButton button {
            background: #fff;
            border: none;
            padding: 10px 20px;
            display: inline-block;
            font-size: 15px;
            font-weight: 450;
            width: 120px;
            text-transform: uppercase;
            cursor: pointer;
            transform: skew(-21deg);
        }

        .handelButton span {
            display: inline-block;
            transform: skew(21deg);
        }

        .handelButton button::before {
            content: '';
            position: absolute;
            top: 0;
            bottom: 0;
            right: 100%;
            left: 0;
            background: rgb(20, 20, 20);
            opacity: 0;
            z-index: -1;
            transition: all 0.5s;
        }

        .handelButton button:hover {
            color: #fff;
        }

        .handelButton button:hover::before {
            left: 0;
            right: 0;
            opacity: 1;
        }


    </style>

</head>
<body>
<!-- 图片放到中间 -->
<div class="container">
    <!-- canvas 图像 -->
    <div class="imageDiv">
        <!-- 大图像 -->
        <div class="handelImageDiv">
            <canvas id="canvas" width="450px" height="450px"></canvas>
        </div>

        <!-- 图像对比 第一次与第二次的对比 -->
        <div class="resultImageDiv">
            <div>
                <canvas id="canvas2" width="160px" height="160px" ></canvas>
                <span>选中图像</span>
            </div>
            <div>
                <img src="" alt="" class="image_download">
                <span>上次截取</span>
            </div>
        </div>
    </div>

    <!-- 遮罩层 -->
    <div class="clipImgDiv">
        <!-- 选中的位置大小 -->
        <div class="moveClipDiv" >
            <!-- 能够选中移动的地方 -->
            <div class="selectMoveDiv"></div>
            <!-- 8个点 -->
            <div class="option dragLeftTop"></div>
            <div class="option dragLeftCenter"></div>
            <div class="option dragLeftBottom"></div>
            <div class="option dragTopCenter"></div>
            <div class="option dragBottomCenter"></div>
            <div class="option dragRightTop"></div>
            <div class="option dragRightCenter"></div>
            <div class="option dragRightBottom"></div>
        </div>
    </div>
    <!-- 按钮与结果层 -->
    <div class="handelButton">
        <button class="uploadImage">
            <span>上传图片</span>
        </button>
        <button class="cutImage">
            <span>截图</span>
        </button>
        <button class="saveImage">
            <span>保存</span>
        </button>
    </div>
</div>
<script>
    //设置的常量
    let scaleWH = 1,
        scaleX = 1,
        scaleY = 1,
        isDrawing = false,
        iCurWidth = 0,
        iCurHeight = 0,
        newImage2 = null,
        canvasSize = 450.
    canvas2Size = 160;

    let params = {
            left: 0,
            top: 0,
            width: 0,
            height: 0,
            currentX: 0,
            currentY: 0,
            flag: false,
            kind: "drag"
        },
        clipImageInfo = {};


    //新建上传按钮
    let fileInput = document.createElement('input');
    fileInput.setAttribute('multiple', 'multiple');
    fileInput.setAttribute('type', 'file');
    fileInput.setAttribute('id', 'fileInput');


    //小图像上的数据
    const canvas2 = document.querySelector('#canvas2');
    let ctx2 = canvas2.getContext("2d");


    //获取对象
    const canvas = document.querySelector("#canvas"),


        //操作截图的按钮对象
        clipBtn = document.querySelector(".clipImgDiv"),
        moveClipDiv = document.querySelector(".moveClipDiv"),
        moveBtn = document.querySelector(".selectMoveDiv"),
        dragLeftTopBtn = document.querySelector(".dragLeftTop"),
        dragLeftCenterBtn = document.querySelector(".dragLeftCenter"),
        dragLeftBottomBtn = document.querySelector(".dragLeftBottom"),
        dragTopCenterBtn = document.querySelector(".dragTopCenter"),
        dragBottomCenterBtn = document.querySelector(".dragBottomCenter"),
        dragRightTopBtn = document.querySelector(".dragRightTop"),
        dragRightCenterBtn = document.querySelector(".dragRightCenter"),
        dragRightBottomBtn = document.querySelector(".dragRightBottom"),

        //底部按钮的对象
        uploadImageBtn = document.querySelector(".uploadImage"),
        cutImageBtn = document.querySelector(".cutImage"),
        saveImageBtn = document.querySelector(".saveImage"),
        imageDownload = document.querySelector(".image_download"),

        //2D类型
        ctx = canvas.getContext("2d");

    //初始化
    window.addEventListener("load",() => {
        //设置画布的宽度与高度
        canvas.width = canvas.offsetWidth;
        canvas.height = canvas.offsetHeight;
        //开始没有遮罩层
        clipBtn.style.display = "none";
        moveClipDiv.style.width = '150px';
        moveClipDiv.style.height = '150px';
        moveClipDiv.style.top = '225px';
        moveClipDiv.style.left = '225px';

        //初始化图片
        loadCanvas()
        //给各个按钮全部绑定事件
        loadHandel()
    })

    const loadCanvas = (base64) => {
        //设置图片
        const img = new Image();
        if(!base64){
            img.src = './1.jpg';
        }else{
            img.src = base64;
        }


        //长宽比适应当前的宽度与高度
        img.onload = function () {
            //段都与高度
            iCurWidth = img.naturalWidth;
            iCurHeight = img.naturalHeight;
            //求出比例
            scaleWH = iCurWidth/iCurHeight;
            //img对象
            imgObject = img

            //在canvas中的大小
            let canvasImageHeight = iCurHeight;
            let canvasImageWidth = iCurWidth;
            let canvasImageTop = 0;
            let canvasImageLeft = 0;


            if(scaleWH > 1){
                canvasImageWidth = canvasSize;
                canvasImageHeight = canvasSize * iCurHeight/iCurWidth;
                canvasImageTop = (canvasSize - canvasImageHeight) / 2 ;
                canvasImageLeft =  0;
            }else{
                canvasImageHeight = canvasSize;
                canvasImageWidth = canvasSize * scaleWH;
                canvasImageTop = 0;
                canvasImageLeft =  (canvasSize - canvasImageWidth) / 2 ;
            }

            ctx.drawImage(img, canvasImageLeft,canvasImageTop , canvasImageWidth, canvasImageHeight);
            scaleX = canvasImageWidth/iCurWidth;
            scaleY = canvasImageHeight/iCurHeight;
        }

        console.log(window.getComputedStyle(clipBtn).getPropertyValue('background-color'));

    }


    //给每个元素加载事件
    const loadHandel = () => {
        startDrag(moveBtn, moveClipDiv, "drag")
        startDrag(dragLeftTopBtn, moveClipDiv, "nw");
        startDrag(dragLeftCenterBtn, moveClipDiv, "w");
        startDrag(dragLeftBottomBtn, moveClipDiv, "sw");
        startDrag(dragTopCenterBtn, moveClipDiv, "n");
        startDrag(dragBottomCenterBtn, moveClipDiv, "s");
        startDrag(dragRightTopBtn, moveClipDiv, "ne");
        startDrag(dragRightCenterBtn, moveClipDiv, "e");
        startDrag(dragRightBottomBtn, moveClipDiv, "se");

    }

    //上传图片
    uploadImageBtn.addEventListener("click",() =>{
        fileInput.click();

    })
    //截图
    cutImageBtn.addEventListener("click",() =>{
        clipBtn.style.display = "";
    })
    //保存
    saveImageBtn.addEventListener("click",() =>{
        saveImage();
    })



    // 打开本地图片
    fileInput.addEventListener('change', function () {

        base64 = getObjectURL(this.files[0]);
        //配置信息
        clipBtn.style.display = "none";
        ctx.clearRect(0,0,canvasSize,canvasSize)
        //重置 图片信息
        loadCanvas(base64);
        loadHandel();

    });
    // 生成本地图片URL地址
    let getObjectURL = function (file) {
        let url = null;
        if (window.createObjectURL !== undefined) { // basic
            url = window.createObjectURL(file);
        } else if (window.webkitURL !== undefined) { // webkit or chrome
            url = window.webkitURL.createObjectURL(file);
        } else if (window.URL !== undefined) { // mozilla(firefox)
            url = window.URL.createObjectURL(file);
        }
        return url;
    };

    // 获取指定元素DOM
    const ID = function (id) {
        return document.getElementById(id);
    };
    const ClassObject  = function(className){
        return document.getElementsByClassName(className)
    }

    //获取相关CSS属性方法
    let getCss = function (o, key) {
        return o.currentStyle ? o.currentStyle[key] : document.defaultView.getComputedStyle(o, false)[key];
    }



    //绑定每个按钮
    var startDrag = function (point, target, kind) {
        //point是拉伸点，target是被拉伸的目标，其高度及位置会发生改变
        //此处的target与上面拖拽的target是同一目标，故其params.left,params.top可以共用，也必须共用
        //初始化宽高
        params.width = getCss(target, "width");
        params.height = getCss(target, "height");
        //初始化坐标
        if (getCss(target, "left") !== "auto") {
            params.left = getCss(target, "left");
        }
        if (getCss(target, "top") !== "auto") {
            params.top = getCss(target, "top");
        }


        //target是移动对象
        point.onmousedown = function (event) {
            params.kind = kind;
            params.flag = true;
            clickFlag = true;
            if (!event) {
                event = window.event;
            }
            var e = event;
            params.currentX = e.clientX;  //鼠标按下时坐标x轴
            params.currentY = e.clientY;  //鼠标按下时坐标y轴
            console.log('params.currentX=', params.currentX);
            console.log('params.currentY=', params.currentY);
            //防止IE文字选中，有助于拖拽平滑
            point.onselectstart = function () {
                return false;
            };

            document.onmousemove = function (event) {

                let e = event ? event : window.event;
                clickFlag = false;
                if (params.flag) {
                    var nowX = e.clientX; // 鼠标移动时x坐标
                    var nowY = e.clientY;   // 鼠标移动时y坐标
                    var disX = nowX - params.currentX;  // 鼠标x方向移动距离
                    var disY = nowY - params.currentY;  // 鼠标y方向移动距离

                    if (params.kind === "n") {
                        // console.log(target.style.top,target.style.height);
                        // //上拉伸
                        // //高度增加或减小，位置上下移动
                        // target.style.top = parseInt(params.top) + disY + "px";
                        // target.style.height = parseInt(params.height) - disY + "px";
                    } else if (params.kind === "w") { //左拉伸
                        // target.style.left = parseInt(params.left) + disX + "px";
                        // target.style.width = parseInt(params.width) - disX + "px";
                    } else if (params.kind === "e") { //右拉伸
                        // target.style.width = parseInt(params.width) + disX + "px";
                    } else if (params.kind === "s") { //下拉伸
                        // target.style.height = parseInt(params.height) + disY + "px";
                    } else if (params.kind === "nw") { //左上拉伸
                        target.style.left = parseInt(params.left) + disX + "px";
                        target.style.width = parseInt(params.width) - disX + "px";
                        target.style.top = parseInt(params.top) + disX + "px";
                        target.style.height = parseInt(params.height) - disX + "px";
                    } else if (params.kind === "ne") { //右上拉伸
                        // target.style.top = parseInt(params.top) - disX + "px";
                        target.style.height = parseInt(params.height) + disX + "px";
                        target.style.width = parseInt(params.width) + disX + "px";
                    } else if (params.kind === "sw") { //左下拉伸
                        // target.style.left = parseInt(params.left) + disX + "px";
                        target.style.width = parseInt(params.width) - disX + "px";
                        target.style.height = parseInt(params.height) - disX + "px";
                    } else if (params.kind === "se") { //右下拉伸
                        target.style.width = parseInt(params.width) + disX + "px";
                        target.style.height = parseInt(params.height) + disX + "px";
                    } else { //移动
                        target.style.left = parseInt(params.left) + disX + "px";
                        target.style.top = parseInt(params.top) + disY + "px";
                        console.log(parseInt(params.top)+"-"+parseInt(params.left))
                    }
                }

                document.onmouseup = function () {
                    params.flag = false;
                    if (getCss(target, "left") !== "auto") {
                        params.left = getCss(target, "left");
                    }
                    if (getCss(target, "top") !== "auto") {
                        params.top = getCss(target, "top");
                    }
                    params.width = getCss(target, "width");
                    params.height = getCss(target, "height");
                    /*console.log('params.width=', params.width);
                    console.log('params.height', params.width);*/

                    //给隐藏文本框赋值
                    posX = parseInt(target.style.left);
                    posY = parseInt(target.style.top);
                    cropW = parseInt(target.style.width);
                    cropH = parseInt(target.style.height);
                    if (posX < 0) {
                        posX = 0;
                    }
                    if (posY < 0) {
                        posY = 0;
                    }
                    if ((posX + cropW) > iCurWidth) {
                        cropW = iCurWidth - posX;
                    }
                    if ((posY + cropH) > iCurHeight) {
                        cropH = iCurHeight - posY;
                    }

                    //赋值 将选中的地方赋予小图像
                    cropImage(posX,posY,cropW,cropH);
                };
            }
        };
    };

    function cropImage( cropPosX, cropPosY, width, height) {
        var newImage = new Image();
        newImage.src = canvas.toDataURL("image/png");
        newImage.width = canvas.height;
        newImage.height = canvas.width;

        newImage.onload  = function () {

            //创建新的canvas对象
            var newCanvas = document.createElement('canvas');
            var newCtx = newCanvas.getContext('2d');
            newCanvas.width = width
            newCanvas.height = height
            newCtx.drawImage(newImage,cropPosX,cropPosY,width,height,0,0,width,height);
            let base64 = newCanvas.toDataURL('image/png');

            //赋予到小的canvas中
            newImage2 = new Image();
            newImage2.src = base64;
            ctx2.clearRect(0,0,canvas2Size,canvas2Size)
            newImage2.onload  = function () {
                let scale2WH = width/height;

                //在canvas中的大小
                let canva2ImageHeight = height;
                let canvas2ImageWidth = width;
                let canvas2ImageTop = 0;
                let canvas2ImageLeft = 0;

                if(scale2WH > 1){
                    canvas2ImageWidth = canvas2Size;
                    canva2ImageHeight = canvas2Size * height/width;
                    canvas2ImageTop = (canvas2Size - canva2ImageHeight) / 2 ;
                    canvas2ImageLeft =  0;
                }else{
                    canva2ImageHeight = canvas2Size;
                    canvas2ImageWidth = canvas2Size * scale2WH;
                    canvas2ImageTop = 0;
                    canvas2ImageLeft =  (canvas2Size - canvas2ImageWidth) / 2 ;
                }

                clipImageInfo.top = canvas2ImageTop
                clipImageInfo.left = canvas2ImageLeft
                clipImageInfo.height = canva2ImageHeight
                clipImageInfo.width = canvas2ImageWidth
                ctx2.drawImage(newImage2, canvas2ImageLeft,canvas2ImageTop , canvas2ImageWidth, canva2ImageHeight);
            }
        }
    };

    saveImage = () =>{
        //赋给图片
        let base64 = canvas2.toDataURL('image/png');

        if (base64 && base64.startsWith('data:image/png;base64,')) {

        } else {
            // 返回值为空或不符合预期格式
            alert("请先截取头像");
            return;
        }

        imageDownload.src = base64;
        //进行下载
        const link = document.createElement('a');
        link.download = `${Date.now()}` + '.jpg';
        link.href = base64;

        // 转换为文件对象
        let file = dataURLtoFile(base64, link.download);

        // 创建 FormData 对象
        let formData = new FormData();
        formData.append('file', file);

        // 发送 POST 请求
        fetch('../user/changer/userimg', {
            method: 'POST',
            body: formData
        }).then(response => {
            if (response.ok) {
                alert("头像修改成功。")
                return response.json(); // 将响应转换为 JSON 对象
            } else {
                alert("头像修改失败。")
                throw new Error('请求失败');
            }
        }).catch(error => {
            // 处理错误
        });
    };

    function dataURLtoFile(dataUrl, filename) {
        var arr = dataUrl.split(','),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);

        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }

        return new File([u8arr], filename, { type: mime });
    }
</script>
</body>
</html>